#ifndef __PIPELINE_H__
#define __PIPELINE_H__

#include "matrix3x3.h"
#include "vector.h"
#include <cmath>
#include <stack>
#include <vector>
#include "utils.h"

class Pipeline{
	public:
		typedef enum Type{POINTS, CIRCLES, LINES, POLYGON};
		typedef enum Side{SIDE_TOP, SIDE_LEFT, SIDE_RIGHT, SIDE_BOTTOM};
    private:
        Matrix3x3 mt;
        Matrix3x3 mv;
        std::stack<Matrix3x3> stack;
        Window window;
		Viewport view;
        Colorf fillColor;
        Colorf lineColor;
        bool fill;

    public:
        Pipeline();
        ~Pipeline();

        /*-----Mt-------*/
        void escale (float ex,float ey);
        void translate(float tx, float ty);
        void rotate (float theta);
        void loadIdentity();
        void pushMatrix();
        void popMatrix();
        /*-----EndMt-----*/

        /*-----Mv-------*/
        void viewport( int top,int left,int right,int bottom );
        void worldWindow(float top, float left, float right, float bottom);
        /*-----EndMv-----*/

        /*-----Primitivas2D-----*/
        void setFillColor(Colorf color);
        void setLineColor(Colorf color);
        /*-----EndPrimitivas2D-----*/

        void setFill(bool fill);
        bool getFill();

        Colorf getFillColor(){ return this->fillColor; }
        Colorf getLineColor(){ return this->lineColor; }

        void draw(Type type,Vertexf* list,unsigned int size);
    private:
		void drawPoints(Vertexf* list,unsigned int size);
		void drawCircles(Vertexf* list,unsigned int size);
		void drawLines(Vertexf* list,unsigned int size);
		void drawPolygon( Polygon& polygon );

        void circleBresenham(Vertexf p1,Polygon& circle);

        void fillScanline(Polygon& polygon);
        void lineBresenham(Vertexi p1,Vertexi p2);

		//Clipping
		bool insideClipRegion(const Vertexf& p,const Viewport& viewport,Side side);
		Vertexf getIntersectPoint(const Vertexf& first,const Vertexf& second,const Viewport& viewport,Side side);
		void clipSide(std::vector<Vertexf>& vertices,const Viewport& viewport,Side side);
		void shClip(Polygon& polygon,const Viewport& viewport);
		bool lbClip(Vertexf* line,const Viewport& viewport);

		void horizontalLine(int x1,int x2,int y);
};

#endif //__PIPELINE_H__
